package com.audi.message;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import lib.relay.ThreadCtrlBase;
import lib.relay.ThreadCtrlBase.ThreadRunListener;
import android.os.Handler;
import android.os.Message;
import android.util.Log;

/**
 * @author PhongNT11
 * 
 */
public class Connector {
	public static final int iTH_TcpSend = 0x00000001;
	public static final int iTH_UdpSend = 0x00000002; // not complete
	public static final int iTH_Offline = 0x00000003;

	public static int SEND_MODE = iTH_Offline;

	private static String ipServer = "127.0.0.1";
	private static int TCP_PORT = 7777;
	private static int UDP_PORT = 8888;
	private static String TAG = "Client";

	private com.audi.box.server.MessageHandler serverMessageHandler;
	private com.audi.handler.MessageHandler clientMessageHandler;

	/**
	 * Connector
	 * 
	 * @see Create thread tcp, udp
	 */
	public Connector() {
		serverMessageHandler = new com.audi.box.server.MessageHandler(null);
		clientMessageHandler = new com.audi.handler.MessageHandler();
	}

	/**
	 * sendMessage
	 * 
	 * @param msg
	 *            String
	 * @param handler
	 *            Handler
	 * @see send message to box
	 */
	public void sendMessage(String msg, Handler handler) {
		Thread sendData = new Thread(new SendDataThread(msg, handler));
		sendData.start();
	}

	public byte[] getBytesFromInputStream(InputStream is) throws IOException {
		byte hi = (byte) is.read();
		if (hi == -1) {
			throw new IOException("End of stream");
		}

		byte lo = (byte) is.read();
		if (lo == -1) {
			throw new IOException("End of stream");
		}

		int size = (hi & 0xFF) * 255 + (lo & 0xFF);
		Log.d(TAG, "[Connector.java] Recieve Tcp size: " + size);
		byte[] data = new byte[size];
		int read = 0;
		while (read != size) {
			int n = is.read(data, read, size - read);
			if (n == -1) {
				throw new IOException("End of stream");
			}
			read += n;
		}

		return data;
	}

	class SendDataThread implements Runnable {
		private Handler handler;
		private String msg;

		/**
		 * 
		 */
		public SendDataThread(String msg, Handler handler) {
			this.msg = msg;
			this.handler = handler;
		}

		@Override
		public void run() {
			int sendMode = SEND_MODE;
			if (sendMode == iTH_TcpSend) {
				Socket m_Socket = null;
				try {
					m_Socket = new Socket();
					m_Socket.connect(new InetSocketAddress(ipServer, TCP_PORT),
							5000);
					InputStream is = m_Socket.getInputStream();
					OutputStream out = m_Socket.getOutputStream();
					if ((is != null) && (out != null)) {
						Log.d(TAG, "[Connector.java] Send Tcp: " + msg);

						byte[] dataSend = msg.getBytes();
						int size = dataSend.length;
						byte hi = (byte) (size / 255);
						byte lo = (byte) (size % 255);
						out.write(hi);
						out.write(lo);
						out.write(dataSend);
						out.flush();

						byte[] data = getBytesFromInputStream(is);
						String strReceive = new String(data);
						Log.d(TAG, "[Connector.java] Receive Tcp: "
								+ strReceive + ", Len : " + data.length);

						Message message = clientMessageHandler
								.processMessage(strReceive);
						handler.handleMessage(message);

						is.close();
						out.close();
					}

					if (m_Socket != null) {
						m_Socket.close();
						m_Socket = null;
					}
				} catch (Exception e) {
					Log.d(TAG, "[Connector.java] Send Tcp Failed.");
					e.printStackTrace();
				}
			} else if (sendMode == iTH_UdpSend) {
				DatagramSocket socket = null;
				try {
					int iUdpPort = UDP_PORT;
					socket = new DatagramSocket(iUdpPort);
					// socket.setTrafficClass(244);
					socket.setBroadcast(false);
					socket.setSoTimeout(5000);

					Log.d(TAG, "[Connector.java] Send Udp: " + msg);
					byte[] ucSend = msg.getBytes();
					InetAddress serverAddr = InetAddress.getByName(ipServer);
					DatagramPacket pktSend = new DatagramPacket(ucSend,
							ucSend.length, serverAddr, iUdpPort);
					socket.send(pktSend);

					byte[] pbtReceive = new byte[1024];
					DatagramPacket pktReceive = new DatagramPacket(pbtReceive,
							pbtReceive.length);
					socket.receive(pktReceive);

					byte[] data = new byte[pktReceive.getLength()];
					System.arraycopy(pbtReceive, 0, data, 0, data.length);
					String strReceive = new String(data);
					Log.d(TAG, "[Connector.java] Receive Udp: " + strReceive
							+ ", Len : " + data.length);
				} catch (Exception ee) {
					Log.d(TAG, "[Connector.java] Send Udp Failed.");

				}
				if (socket != null)
					socket.close();
			} else if (sendMode == iTH_Offline) {
				Log.d(TAG, "[Connector.java] Send Offline: " + msg);
				String strReceive = serverMessageHandler.processMessage(msg);
				Log.d(TAG, "[Connector.java] Receive Offline: " + strReceive);

				Message message = clientMessageHandler
						.processMessage(strReceive);
				handler.handleMessage(message);
			}
		}

	}
}
